import {
  AuthenticationClientHttpRequestInterceptor,
  AuthenticationStrategy,
  AuthenticationToken,
  CodecFeignClientExecutorInterceptor,
  DateEncoder,
  HttpMediaType,
  HttpRequest,
  HttpResponse,
  HttpStatus,
  NetworkClientHttpRequestInterceptor,
  ProcessBarExecutorInterceptor,
  ProgressBarOptions,
  RoutingClientHttpRequestInterceptor,
  SimpleNetworkStatusListener,
  stringDateConverter,
  UnifiedFailureToastExecutorInterceptor
} from 'fengwuxp-typescript-feign'
import {
  ClientHttpInterceptorRegistry,
  FeignClientInterceptorRegistry,
  FeignConfigurationAdapter,
  feignConfigurationInitializer,
} from 'feign-boot-starter'
import { BrowserHttpAdapter, BrowserNetworkStatusListener } from 'feign-boot-browser-stater'
import { api, APP_ID, APP_SECRET, CHANNEL_CODE } from './config'
import Loading from '@/components/libs/loading'
import { message } from 'ant-design-vue'
import { adminInfoSession, frameActiveMenuSession, frameMenuSession } from '@/storage'
import { macKeyCookie } from '@/storage/cookie/index'
import { redirectToLogin } from '@/router'
import { OakApiSignatureStrategy } from 'oak-common'
import { handleMaintain } from '@/plugins/src/vmaAssist/handleError'

class AppAuthenticationStrategy implements AuthenticationStrategy {

  public appendAuthorizationHeader = (authorization: AuthenticationToken, headers: Record<string, string>) => {
    // console.log(macKeyCookie.get())
    // @ts-ignore
    headers.Authorization = macKeyCookie.get() // authorization.authorization
    return headers
  }

  // @ts-ignore
  public getAuthorization = (req: Readonly<HttpRequest>) => {
    return { authorization: '99', expireDate: '' }
  }

  // @ts-ignore
  public refreshAuthorization = (authorization: AuthenticationToken, req: Readonly<HttpRequest>) => {


  }
}

interface RestfulApiResp<T = any> {
  /**
   * 请求结果code 0表示成功，其他均为失败
   */
  readonly errorCode: number
  /**
   * 请求结果 消息
   */
  readonly errorMessage: string

  /**
   * 请求结果数据
   */
  readonly data: T
  /**
   * 请求是否成功
   */
  readonly success: boolean

}

// tslint:disable-next-line:max-classes-per-file
class BrowserFeignConfigurationAdapter implements FeignConfigurationAdapter {

  public loadingInstance: any

  public defaultProduce = () => HttpMediaType.FORM_DATA

  public httpAdapter = () => new BrowserHttpAdapter(20 * 1000)
  public apiSignatureStrategy = () => {
    return new OakApiSignatureStrategy(APP_ID, APP_SECRET, CHANNEL_CODE, false)
  }

  public registryClientHttpRequestInterceptors = (interceptorRegistry: ClientHttpInterceptorRegistry) => {
    interceptorRegistry.addInterceptor(new NetworkClientHttpRequestInterceptor(
      new BrowserNetworkStatusListener(),
      new SimpleNetworkStatusListener()))
    interceptorRegistry.addInterceptor(new RoutingClientHttpRequestInterceptor(api))
    interceptorRegistry
      // @ts-ignore
      .addInterceptor(new AuthenticationClientHttpRequestInterceptor(new AppAuthenticationStrategy()))
    // .excludePathPatterns('/login')
  }

  public registryFeignClientExecutorInterceptors = (interceptorRegistry: FeignClientInterceptorRegistry) => {
    const that = this
    interceptorRegistry.addInterceptor(new ProcessBarExecutorInterceptor({
      hideProgressBar() {
        Loading.hide()
      },
      // @ts-ignore
      showProgressBar(options: ProgressBarOptions) {
        Loading.show()
      }
    }))

    // codec
    interceptorRegistry.addInterceptor(new CodecFeignClientExecutorInterceptor(
      [
        // 将时间类型转换为 时间戳格式
        new DateEncoder(stringDateConverter()),
      ],
    ))
    const toAuthenticationViewHandle = () => {
      macKeyCookie.remove()
      adminInfoSession.remove()
      frameActiveMenuSession.remove()
      frameMenuSession.remove()
      redirectToLogin()
    }
    // 统一数据转换，错误提示
    interceptorRegistry.addInterceptor(new UnifiedFailureToastExecutorInterceptor(
      (response: HttpResponse | string) => {
        let text = response as any
        if (typeof response === 'object') {
          text = response.statusText
          const statusCode = response.statusCode
          if (statusCode === HttpStatus.UNAUTHORIZED) {
            text = '登录过期'
            message.error(text as string)
            setTimeout(toAuthenticationViewHandle, 1800)
          } else if (statusCode === HttpStatus.GATEWAY_TIMEOUT) {
            text = '请求超时'
          } else if (statusCode === HttpStatus.BAD_GATEWAY) {
            text = '服务不可用'
            handleMaintain(text)
          } else {
            const data = response.data
            if (data != null) {
              text = data.errorMessage
            }
            if (data.message === 'Failed to fetch') {
              handleMaintain(text)
              return
            }
            if (data.errorCode === 200001) {
              // 用户被挤下线
              setTimeout(toAuthenticationViewHandle, 1800)
            }
          }
        }
        const content = text || '请求异常'
        message.error(content as string)
      },
      toAuthenticationViewHandle))
  }
  public getBusinessResponseExtractor = () => {
    return (responseBody: RestfulApiResp) => {
      if (responseBody.success) {
        return Promise.resolve(responseBody.data)
      }
      // 业务处理失败
      return Promise.reject(responseBody)
    }
  }

  public feignUIToast = () => (text: string) => {
    message.info(text)
  }
}


/**
 * 注册feign 代理
 */
// console.log("注册feign")
// @ts-ignore
feignConfigurationInitializer(new BrowserFeignConfigurationAdapter())
